package com.tencent.iov.cowin.befsale.clue.service.cus.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.google.common.collect.Lists;
import com.tencent.iov.cowin.befsale.clue.controller.cus.vo.request.QueryCustomerRequest;
import com.tencent.iov.cowin.befsale.clue.controller.cus.vo.response.CustomerResponse;
import com.tencent.iov.cowin.befsale.clue.domain.clue.po.ClueCustomerCollect;
import com.tencent.iov.cowin.befsale.clue.domain.cus.po.CustomerBehavior;
import com.tencent.iov.cowin.befsale.clue.domain.cus.vo.CustomerBehaviorStatistical;
import com.tencent.iov.cowin.befsale.clue.repository.cus.CustomerBehaviorManager;
import com.tencent.iov.cowin.befsale.clue.service.clue.ClueCustomerCollectService;
import com.tencent.iov.cowin.befsale.clue.service.cus.*;
import com.tencent.iov.cowin.befsale.clue.service.cus.CustomerBehaviorService;
import com.tencent.iov.cowin.befsale.clue.service.cus.DealerCustomerService;
import com.tencent.iov.cowin.befsale.clue.value.enums.CustomerTypeEnum;
import com.tencent.iov.cowin.befsale.clue.value.enums.FollowRecordSecondStatusEnum;
import com.tencent.iov.cowin.befsale.clue.value.enums.FollowRecordStatusEnum;
import com.software.boot.common.exception.BusinessException;
import com.software.boot.common.exception.NEError;
import com.software.boot.common.model.dao.PageRequest;
import com.software.boot.common.model.dao.PageResponse;
import com.software.boot.common.util.BeanUtil;
import com.software.boot.common.util.DateUtil;
import com.software.boot.common.util.EmptyUtils;
import com.software.boot.common.util.ValidateUtils;
import com.software.common.enums.DeleteEnum;
import com.tencent.iov.cowin.befsale.clue.service.cus.CustomerFollowRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Describe: 客户行为标签统计表（线索中心需求建表）_Service实现层
 * @author: xiamu
 * @created: 2022-01-11 16:00:50
 * @version: 1.0
 */
@Service
@Slf4j
public class CustomerBehaviorServiceImpl implements CustomerBehaviorService {

    @Autowired
    private CustomerBehaviorManager customerBehaviorManager;
    @Autowired
    private CustomerFollowRecordService customerFollowRecordService;
    @Autowired
    private DealerCustomerService dealerCustomerService;
    @Autowired
    private ClueCustomerCollectService clueCustomerCollectService;

    @Override
    public CustomerBehavior getDetailById(Long id) {
        // 验证请求参数
        ValidateUtils.checkLongGTZero(id, "ID不能为空或小于0");
        //处理业务
        CustomerBehavior customerBehavior = customerBehaviorManager.getDetailById(id);
        if (EmptyUtils.isNotEmpty(customerBehavior)) {
            return BeanUtil.copy(customerBehavior, CustomerBehavior.class);
        }
        //返回结果
        return null;
    }

    @Override
    public int insert(CustomerBehavior request) {
        //验证请求参数
        //处理业务
        //封装返回值
        return customerBehaviorManager.insert(request);
    }

    @Override
    public int insertBatch(List<CustomerBehavior> requests) {
        //验证请求参数
        //处理业务
        //封装返回值
        return customerBehaviorManager.insertBatch(requests);
    }

    @Override
    public int update(CustomerBehavior request) {

        //验证请求参数
        //处理业务
        //返回对象
        return customerBehaviorManager.update(request);
    }

    @Override
    public int delete(CustomerBehavior request) {
        Long id = request.getId();
        //验证请求参数 /
        ValidateUtils.checkObjNull(id, "请求参数不能为空");
        ValidateUtils.checkIntNotNullAndGTZero(id.intValue(), "ID不能为空或小于0");
        //处理业务
        CustomerBehavior customerBehavior = new CustomerBehavior();
        customerBehavior.setId(id);
        //返回对象
        return customerBehaviorManager.update(customerBehavior);
    }

    @Override
    public List<CustomerBehavior> getListByParam(CustomerBehavior request) {
        //验证请求参数
        //可以设置排序
        //处理业务
        List<CustomerBehavior> queryList = customerBehaviorManager.getListByParam(request);
        // 返回结果
        if (CollectionUtils.isNotEmpty(queryList)) {
            return BeanUtil.copyByList(queryList, CustomerBehavior.class);
        }
        return new ArrayList<>();
    }

    @Override
    public PageResponse<CustomerBehavior> getPageByParam(PageRequest<CustomerBehavior> request) {
        //验证请求参数
        ValidateUtils.checkObjNull(request, "请求参数不能为空");
        //可以设置排序 query.orderByCreatedTime(true);
        //处理业务
        RowBounds rowBounds = new RowBounds(request.getPageNum(), request.getPageSize());
        Page<CustomerBehavior> queryPageList = customerBehaviorManager.getPageByParam(request.getParamData(), rowBounds);
        PageResponse<CustomerBehavior> pageResponse = new PageResponse<>();
        pageResponse.converPageResponse(pageResponse, queryPageList, request);
        pageResponse.setDataList(BeanUtil.copyByList(queryPageList.getResult(), CustomerBehavior.class));
        //返回结果
        return pageResponse;
    }

    @Override
    public CustomerBehavior getOneByParam(CustomerBehavior request) {
        return customerBehaviorManager.getOneByParam(request);
    }

    @Override
    public CustomerBehavior statisticalByCusId(CustomerBehavior request) {
        return customerBehaviorManager.statisticalByCusId(request);
    }

    @Override
    public Boolean statisticalCustomerBehavior(String startDateStr, String endDateStr) {
        if (EmptyUtils.isEmpty(startDateStr) && EmptyUtils.isNotEmpty(endDateStr)) {
            throw new BusinessException(NEError.INVALID_PARAMETER, "参数出入不正确");
        }
        if (EmptyUtils.isEmpty(endDateStr) && EmptyUtils.isNotEmpty(startDateStr)) {
            throw new BusinessException(NEError.INVALID_PARAMETER, "参数出入不正确");
        }

        //补偿数据流程
        if (EmptyUtils.isNotEmpty(startDateStr) && EmptyUtils.isNotEmpty(endDateStr)) {
            Date startDate = DateUtil.getDate(startDateStr);
            Date endDate = DateUtil.getDate(endDateStr);
            if (startDate.after(endDate) || startDate.equals(endDate)) {
                log.error("[CustomerBehaviorService][statisticalCustomerBehavior] startDate > endDate");
                return false;
            }
            while (startDate.before(endDate) && !startDate.equals(endDate)) {
                Date temEndDate = DateUtil.addDate(startDate, 1);

                //删除已保存当天数据
                customerBehaviorManager.deleteByDay(startDate);

                //总部数据统计
                saveOemCustomerBehavior(startDate, temEndDate);

                //经销商数据统计
                saveDealerCustomerBehavior(startDate, temEndDate);

                //赋值进入一下一个循环
                startDate = temEndDate;
            }
        }
        //自动跑job流程
        if (EmptyUtils.isEmpty(startDateStr) && EmptyUtils.isEmpty(endDateStr)) {
            Date endDate = DateUtils.truncate(new Date(), Calendar.DATE);
            Date startDate = DateUtil.addDate(endDate, -1);

            //删除已保存当天数据
            customerBehaviorManager.deleteByDay(startDate);
            //总部数据统计
            saveOemCustomerBehavior(startDate, endDate);

            //经销商数据统计
            saveDealerCustomerBehavior(startDate, endDate);
        }
        //总部标签统计（宽表）
        statisticalOemCustomer();

        //经销商标签统计（宽表）
        statisticalDealerCustomer();
        return true;
    }

    private void statisticalOemCustomer() {
        List<CustomerBehavior> oemCustomerBehaviors = customerBehaviorManager.statisticalByCusType(CustomerTypeEnum.CUSTOMER_TYPE_OEM.getCode());
        if (EmptyUtils.isEmpty(oemCustomerBehaviors)) {
            return;
        }
        List<Long> cusIds = oemCustomerBehaviors.stream().map(CustomerBehavior::getOemCusId).collect(Collectors.toList());
        QueryCustomerRequest request = new QueryCustomerRequest();
        request.setOemCusIds(cusIds);
        request.setDeleted(DeleteEnum.INIT.getFlag());
        //找到对应经销商客户信息
        List<CustomerResponse> customerResponses = dealerCustomerService.getListByParam(request);
        Map<Long, List<CustomerResponse>> dealerMap = null;
        if (EmptyUtils.isNotEmpty(customerResponses)) {
            dealerMap = customerResponses.stream().collect(Collectors.groupingBy(CustomerResponse::getOemCusId));
        }
        Map<Long, List<CustomerResponse>> finalDealerMap = dealerMap;
        oemCustomerBehaviors.forEach(oemCustomerBehavior -> {
            Long oemCusId = oemCustomerBehavior.getOemCusId();
            if (EmptyUtils.isNotEmpty(finalDealerMap) && finalDealerMap.containsKey(oemCusId)
                    && EmptyUtils.isNotEmpty(finalDealerMap.get(oemCusId))) {
                finalDealerMap.get(oemCusId).forEach(customerResponse -> {
                    //构建更新块表数据
                    ClueCustomerCollect updateClueCollect = new ClueCustomerCollect();
                    updateClueCollect.setCusId(customerResponse.getId());
                    updateClueCollect.setDealerId(customerResponse.getDealerId());
                    updateClueCollect.setTenantId(customerResponse.getTenantId());
                    updateClueCollect.setCorpId(customerResponse.getCorpId().toString());
                    updateClueCollect.setOemCusBehavior(JSON.toJSONString(oemCustomerBehavior));
                    clueCustomerCollectService.updateByCusIdsAndDealerId(updateClueCollect);
                });
                return;
            }
            //构建更新块表数据
            ClueCustomerCollect updateClueCollect = new ClueCustomerCollect();
            updateClueCollect.setCusId(oemCusId);
            updateClueCollect.setTenantId(oemCustomerBehavior.getTenantId());
            updateClueCollect.setCorpId(oemCustomerBehavior.getCorpId());
            updateClueCollect.setOemCusBehavior(JSON.toJSONString(oemCustomerBehavior));
            clueCustomerCollectService.updateByCusIdsAndDealerId(updateClueCollect);
        });
    }

    private void statisticalDealerCustomer() {
        List<CustomerBehavior> dealerCustomerBehaviors = customerBehaviorManager.statisticalByCusType(CustomerTypeEnum.CUSTOMER_TYPE_DEALER.getCode());
        if (EmptyUtils.isEmpty(dealerCustomerBehaviors)) {
            return;
        }
        dealerCustomerBehaviors.forEach(dealerCustomerBehavior -> {
            //构建更新块表数据
            ClueCustomerCollect updateClueCollect = new ClueCustomerCollect();
            updateClueCollect.setCusId(dealerCustomerBehavior.getDealerCusId());
            updateClueCollect.setDealerId(dealerCustomerBehavior.getDealerId());
            updateClueCollect.setTenantId(dealerCustomerBehavior.getTenantId());
            updateClueCollect.setCorpId(dealerCustomerBehavior.getCorpId());
            updateClueCollect.setDealerCusBehavior(JSON.toJSONString(dealerCustomerBehavior));
            clueCustomerCollectService.updateByCusIdsAndDealerId(updateClueCollect);
        });
    }


    public void saveDealerCustomerBehavior(Date startDate, Date endDate) {
        //跟进统计数据查询 分类1
        List<Integer> statues = Lists.newArrayList(FollowRecordStatusEnum.FOLLOW_UP.getCode(),
                FollowRecordStatusEnum.APPROVAL.getCode());
        List<CustomerBehaviorStatistical> dealerFirstBehaviors = customerFollowRecordService.statisticalByStatus(startDate, endDate, statues, CustomerTypeEnum.CUSTOMER_TYPE_DEALER.getCode());
        if (EmptyUtils.isEmpty(dealerFirstBehaviors)) {
            return;
        }
        List<CustomerBehaviorStatistical> followList = dealerFirstBehaviors.stream()
                .filter(dealerFirstBehavior -> FollowRecordStatusEnum.FOLLOW_UP.getCode().equals(dealerFirstBehavior.getStatus())).collect(Collectors.toList());
        Map<Long, CustomerBehaviorStatistical> dealerStatusMap;
        if (EmptyUtils.isEmpty(followList)) {
            return;
        }
        dealerStatusMap = followList.stream()
                .collect(Collectors.toMap(CustomerBehaviorStatistical::getDealerCusId, oemFirstBehavior -> oemFirstBehavior, (oldValue, newValue) -> newValue));
        List<Long> cusIds = dealerFirstBehaviors.stream().map(CustomerBehaviorStatistical::getDealerCusId).distinct().collect(Collectors.toList());

        //到店（到店+试乘试驾）、试驾、战败激活 分类2
        List<Integer> secondStatus = Lists.newArrayList(FollowRecordSecondStatusEnum.APPROVAL_FAIL_ACTIVATE.getCode(),
                FollowRecordSecondStatusEnum.FOLLOW_CHECKIN.getCode(),
                FollowRecordSecondStatusEnum.FOLLOW_DRIVE_TEST.getCode());
        List<CustomerBehaviorStatistical> dealerSecondBehaviors = customerFollowRecordService.statisticalBySecondStatus(startDate, endDate, secondStatus, CustomerTypeEnum.CUSTOMER_TYPE_DEALER.getCode());
        Map<Long, List<CustomerBehaviorStatistical>> secondMap = null;
        if (EmptyUtils.isNotEmpty(dealerSecondBehaviors)) {
            secondMap = dealerSecondBehaviors.stream().collect(Collectors.groupingBy(CustomerBehaviorStatistical::getDealerCusId));
        }
        if (EmptyUtils.isEmpty(dealerStatusMap) && EmptyUtils.isEmpty(secondMap)) {
            return;
        }

        //处理数据
        List<CustomerBehavior> customerBehaviors = getCustomerBehaviorList(cusIds, dealerStatusMap, secondMap, startDate);
        if (EmptyUtils.isEmpty(customerBehaviors)) {
            return;
        }

        customerBehaviorManager.insertBatch(customerBehaviors);
    }


    public void saveOemCustomerBehavior(Date startDate, Date endDate) {
        //跟进统计数据查询 分类1
        List<Integer> statues = Lists.newArrayList(FollowRecordStatusEnum.FOLLOW_UP.getCode(),
                FollowRecordStatusEnum.APPROVAL.getCode());
        List<CustomerBehaviorStatistical> oemFirstBehaviors = customerFollowRecordService.statisticalByStatus(startDate, endDate, statues, CustomerTypeEnum.CUSTOMER_TYPE_OEM.getCode());
        if (EmptyUtils.isEmpty(oemFirstBehaviors)) {
            return;
        }
        List<CustomerBehaviorStatistical> followList = oemFirstBehaviors.stream()
                .filter(oemFirstBehavior -> FollowRecordStatusEnum.FOLLOW_UP.getCode().equals(oemFirstBehavior.getStatus())).collect(Collectors.toList());
        Map<Long, CustomerBehaviorStatistical> oemStatusMap;
        if (EmptyUtils.isEmpty(followList)) {
            return;
        }
        oemStatusMap = followList.stream()
                .collect(Collectors.toMap(CustomerBehaviorStatistical::getOemCusId, oemFirstBehavior -> oemFirstBehavior, (oldValue, newValue) -> newValue));
        List<Long> cusIds = oemFirstBehaviors.stream().map(CustomerBehaviorStatistical::getOemCusId).distinct().collect(Collectors.toList());

        //到店（到店+试乘试驾）、试驾、战败激活 分类2
        List<Integer> secondStatus = Lists.newArrayList(FollowRecordSecondStatusEnum.APPROVAL_FAIL_ACTIVATE.getCode(),
                FollowRecordSecondStatusEnum.FOLLOW_CHECKIN.getCode(),
                FollowRecordSecondStatusEnum.FOLLOW_DRIVE_TEST.getCode());
        List<CustomerBehaviorStatistical> oemSecondBehaviors = customerFollowRecordService.statisticalBySecondStatus(startDate, endDate, secondStatus, CustomerTypeEnum.CUSTOMER_TYPE_OEM.getCode());
        Map<Long, List<CustomerBehaviorStatistical>> secondMap = null;
        if (EmptyUtils.isNotEmpty(oemSecondBehaviors)) {
            secondMap = oemSecondBehaviors.stream().collect(Collectors.groupingBy(CustomerBehaviorStatistical::getOemCusId));
        }
        if (EmptyUtils.isEmpty(oemStatusMap) && EmptyUtils.isEmpty(secondMap)) {
            return;
        }

        //处理数据
        List<CustomerBehavior> customerBehaviors = getCustomerBehaviorList(cusIds, oemStatusMap, secondMap, startDate);
        if (EmptyUtils.isEmpty(customerBehaviors)) {
            return;
        }
        customerBehaviorManager.insertBatch(customerBehaviors);
    }

    private List<CustomerBehavior> getCustomerBehaviorList(List<Long> cusIds, Map<Long, CustomerBehaviorStatistical> statusMap,
                                                           Map<Long, List<CustomerBehaviorStatistical>> secondStatusMap, Date startDate) {
        List<CustomerBehavior> customerBehaviors = Lists.newArrayList();
        cusIds.forEach(cusId -> {
            CustomerBehavior customerBehavior = null;
            if (EmptyUtils.isNotEmpty(statusMap) && statusMap.containsKey(cusId) && EmptyUtils.isNotEmpty(statusMap.get(cusId))) {
                CustomerBehaviorStatistical customerStatistical = statusMap.get(cusId);
                customerBehavior = BeanUtil.copy(customerStatistical, CustomerBehavior.class);
                customerBehavior.setFollowUpTimes(customerStatistical.getNumber());
                customerBehavior.setDeleted(DeleteEnum.INIT.getFlag());
                customerBehavior.setCusType(CustomerTypeEnum.CUSTOMER_TYPE_OEM.getCode());
                if (EmptyUtils.isNotEmpty(customerStatistical.getDealerCusId()) && customerStatistical.getDealerCusId() > 0) {
                    customerBehavior.setCusType(CustomerTypeEnum.CUSTOMER_TYPE_DEALER.getCode());
                }
            }
            if (EmptyUtils.isNotEmpty(secondStatusMap) && secondStatusMap.containsKey(cusId) && EmptyUtils.isNotEmpty(secondStatusMap.get(cusId))) {
                if (EmptyUtils.isEmpty(customerBehavior)) {
                    customerBehavior = new CustomerBehavior();
                }
                fillSecondStatusStatistical(secondStatusMap.get(cusId), customerBehavior);
            }
            if (EmptyUtils.isEmpty(customerBehavior)) {
                return;
            }
            customerBehavior.setDay(startDate);
            customerBehaviors.add(customerBehavior);
        });
        return customerBehaviors;
    }

    private void fillSecondStatusStatistical(List<CustomerBehaviorStatistical> behaviors, CustomerBehavior customerBehavior) {
        behaviors.forEach(behavior -> {
            if (FollowRecordSecondStatusEnum.FOLLOW_CHECKIN.getCode().equals(behavior.getSecondStatus())
                    || FollowRecordSecondStatusEnum.FOLLOW_DRIVE_TEST.getCode().equals(behavior.getSecondStatus())) {
                Integer visitTimes = EmptyUtils.isEmpty(customerBehavior.getVisitTimes()) ? 0 : customerBehavior.getVisitTimes();
                customerBehavior.setVisitTimes(visitTimes + behavior.getNumber());
            }
            if (FollowRecordSecondStatusEnum.FOLLOW_DRIVE_TEST.getCode().equals(behavior.getSecondStatus())) {
                customerBehavior.setTestDrivesTimes(behavior.getNumber());
            }
            if (FollowRecordSecondStatusEnum.APPROVAL_FAIL_ACTIVATE.getCode().equals(behavior.getSecondStatus())) {
                customerBehavior.setFailActivationsTimes(behavior.getNumber());
            }
            customerBehavior.setOemCusId(behavior.getOemCusId());
            customerBehavior.setDealerCusId(behavior.getDealerCusId());
            customerBehavior.setDealerId(behavior.getDealerId());
            customerBehavior.setTenantId(behavior.getTenantId());
            customerBehavior.setCorpId(behavior.getCorpId());
            customerBehavior.setDeleted(DeleteEnum.INIT.getFlag());
            customerBehavior.setCusType(CustomerTypeEnum.CUSTOMER_TYPE_OEM.getCode());
            if (EmptyUtils.isNotEmpty(behavior.getDealerCusId()) && behavior.getDealerCusId() > 0) {
                customerBehavior.setCusType(CustomerTypeEnum.CUSTOMER_TYPE_DEALER.getCode());
            }
        });
    }
}
